

local Item = class("Item")

local string_ulen = string.ulen
local string_usub = string.usub
local string_isContain = string.isContain
local string_split = string.split

-- 道具名字显示最大字符，多余的需要截取加...
local SHOW_NAME_MAX_LEN = Constant.ITEM_SHOW_NAME_MAX_LEN

--拍卖行消耗品ID
local AUCTIONSHOP_NORMAL_MINID = 1200
local AUCTIONSHOP_NORMAL_MAXID = 1300
local AUCTIONSHOP_BID_MINID = 2200
local AUCTIONSHOP_BID_MAXID = 2300

function Item:ctor(itemBagType)
	self.itemBagType=itemBagType
	self.uid = ""
	self.tid= 0
	-- self.bind = 0
	self.amount = 0
	self.isNew = false

	self._shareData = nil  -- 用于聊天分享的数据

	self.extraProps = nil -- 属性条卷轴增加的额外属性
end

function Item:isValid()
	if self.itemBagType==Enums.ItemBagType.equip then
		return GD:getCachedValue("equip2",self.tid)~=nil
	elseif self.itemBagType==Enums.ItemBagType.item then
		return GD:getCachedValue("item",self.tid)~=nil
	elseif self.itemBagType==Enums.ItemBagType.mount then
        return GD:getCachedValue("mount",self.tid)~=nil
	elseif self.itemBagType==Enums.ItemBagType.tool then
        return GD:getCachedValue("tool",self.tid)~=nil
    elseif self.itemBagType==Enums.ItemBagType.jewel then
    	return GD:getCachedValue("jewel2",self.tid)~=nil
    else
    	return true
	end
end

function Item:read(value)
    --dump(value,"Item:read",15)

	self.uid = value.uid
	self.tid= value.tid
	-- self.bind = value.bind
	self.isNew = value.isNew or false
	if self.itemBagType == Enums.ItemBagType.item then
		self.amount = value.amount
	elseif self.itemBagType == Enums.ItemBagType.jewel then
		self.amount = 1
	else
		self.amount = 1
	end

	self._icon = nil
	self._showName = nil

	self._breakType = nil
	self._breakId = nil
	self._breakNum = nil

	self._sellType = nil
	self._sellId = nil
	self._sellNum = nil

	self:initDB()
end

function Item:initDB()
	local conf = GD:queryItemById(self.tid)
	if DEBUG > 0 then
		assert(conf ~= nil, "Item.conf can't be nil " .. self.tid)
	else
		if not conf then
			conf =  {}
			release_print("Item.conf can't be nil " .. (self.tid or "nil"))
		end
	end
	self.conf = conf

	self.quality = tonumber(conf.quality or 1)
	self.orderIndex = tonumber(conf.orderIndex or 1000)
	self.useLv = tonumber(conf.useLv or 1)
	self.type = tonumber(conf.type) -- 道具类型
	self.showType = tonumber(conf.showType or 0) -- 显示类型
	self.bindType = tonumber(conf.bind or 0) -- 绑定类型
	self.useType = tonumber(conf.useType or 0) -- 使用类型
	self.trackNpcId = tonumber(conf.trackNpcId or 0) -- 追踪npc
    self.subMenu = tonumber(conf.subMenu or 0) --拍卖行出售背包显示类型

	self.name = conf.name or ""
	self.desc = conf.desc or ""

	self:getSpecialInfo() -- 如果是属性条卷轴，要初始化额外属性
end

function Item:setAmount(num)
	self.amount = num
end

function Item:getAmount()
	return self.amount
end

function Item:setShareData(shareData)
	self._shareData = shareData
end
function Item:getShareData()
	return self._shareData
end

function Item:getId()
	return self.tid
end

function Item:getUid()
	return self.uid
end

function Item:getQuality()
	return self.quality
end

--道具的拍卖类型 0不出售 1 普通 2 竞价
function Item:getAcType()
	return tonumber(self.conf.acType or 0)
end

--获得道具的子分类
function Item:getSubMenu()
	return tonumber(self.conf.subMenu)
end

--道具的指导价
function Item:getSuggestPrice()
	return tonumber(self.conf.defaultPrice or 0)
end

--道具的最低售价
function Item:getMinSoldPrice()
	return tonumber(self.conf.minPrice or 0)
end

--道具的最高售价
function Item:getMaxSoldPrice()
	return tonumber(self.conf.maxPrice or 0)
end

--所得税比率 万分之一
function Item:getAcRatio()
	return tonumber(self.conf.ratio or 0)
end

--最小数量
function Item:getAcMinNum()
	return tonumber(self.conf.minNum or 0)
end

--最大数量
function Item:getAcMaxNum()
	return tonumber(self.conf.maxNum or 0)
end

-- isFull true/false 是否取全名
-- maxLen number 自定义截取最大字数
-- 名字默认按6个utf8字符计算，多于6个的截取5个加...
function Item:getName(isFull, maxLen)
	isFull = isFull or false
	if isFull then
		return L(self.name)
	else
		if maxLen and maxLen ~= SHOW_NAME_MAX_LEN then
			local name = L(self.name)
			local len = string_ulen(name)
			if len > maxLen then
				return string_usub(name, 1, maxLen-1) .. "..."
			else
				return name
			end
		else
			if not self._showName then
				local name = L(self.name)
				local len = string_ulen(name)
				if len > SHOW_NAME_MAX_LEN then
					self._showName = string_usub(name, 1, SHOW_NAME_MAX_LEN-1) .. "..."
				else
					self._showName = name
				end
			end
			return self._showName
		end
	end
end

function Item:getDesc()
	return L(self.desc or "")
end

function Item:getIcon()
	if not self._icon then
       self._icon = string.format("%s%s.png", Res.itemPath, self.conf.icon or "")
    end
    return self._icon
end

function Item:getIconBg()
	return Res.Qulity_Icon_Bg[self.quality]
end

-- 获取类型名字描述
function Item:getTypeName()
	if self:isTransAttr() then
		return self:getExtraAttrTypeName()
	else
		if self.showType > 0 then
			return L(Res.showTypeName .. self.showType)
		else
			return ""
		end
	end
end

-- 是否是属性条卷轴
function Item:isTransAttr()
	return self:getItemType() == Enums.ItemType.transattr
end

-- 属性条显示的类型名字描述（战士手专用\n闪避+%5）
function Item:getExtraAttrTypeName()
	local str = string.format(L("classlimit"), L("class_"..self:getClass()))
	if self.conf.specialInfo then
		local temp = string_split(self.conf.specialInfo, "|")
		local propId = temp[5] and tonumber(temp[5])
		local val = temp[6] and tonumber(temp[6])
		local strTemp = UD:_formatChangedAttr(propId, val)
		if strTemp then
			str = str .. "\n" .. strTemp
		end
	end
	return str
end

function Item:getItemType()
	if self.itemBagType==Enums.ItemBagType.item then
		return self.type
	else
		print("Item:getItemType only suport Item")
	end
end

function Item:getUseValue()
	return self.conf.useValue
end

-- 使用之后掉落的物品id
function Item:getDropLoot()
	local dropId = self.conf.drop
	if dropId and not self._dropLoot then
		self._dropLoot = UD:parseDropToLoot(dropId)
	end
	return self._dropLoot
end

function Item:getResource()
	-- self.subMenu 用于拍卖行跳转。
	local resource = GD:getConvertResource(self.conf.getResource, Enums.ItemBagType.item, tonumber(self.conf.ID), self.subMenu)
	return resource
end

function Item:getClass()
	return self.conf.class or "0"
end

-- 是适合职业的道具/装备，"0"适合所有职业，默认是自己的职业
function Item:isClassEnable(classId)
	if classId then
		local classStr = self:getClass()
		return classStr == "0" or string_isContain(classStr, classId)
	else
		-- 自己职业的适合判定缓存起来
		if self._isClassEnable == nil then
			local classStr = self:getClass()
			classId = UD:getClass()
			self._isClassEnable = classStr == "0" or string_isContain(classStr, classId)
		end
		return self._isClassEnable
	end
end

-- 检测道具是否有可以预览的外显
-- return 是否可以，预览参数
function Item:isClassAvatarEnable(classId)
	if self.itemBagType ~= Enums.ItemBagType.item then return false end
	if not self.conf.preview then return false end

	if not self._avatarParams then
		local ary = string.split(self.conf.preview, "|")
		self._avatarParams = {type=tonumber(ary[1]), id=tonumber(ary[2])}
	end

	if self._avatarParams.type == Enums.AvatarPreviewType.equip then
		classId = classId or UD:getClass()
		local isEnable = GD:isEquipClassAvatarEnable(self._avatarParams.id, classId)
		return isEnable, isEnable and self._avatarParams or nil
	elseif self._avatarParams.type == Enums.AvatarPreviewType.partner then
		local p = UD.partnersData:getPartnerById(self._avatarParams.id)
		if p then
			local params = {type=Enums.AvatarPreviewType.partner, data = p}
			return true, params
		end
		return false
	else
		return true, self._avatarParams
	end
end

-- 是否是材料
function Item:isMaking()
	-- 常量 6 为策划定义的材料
	return 6 == self.orderIndex
end

-- 使用时依赖的其他道具id
function Item:getDependOnId()
	return self.conf.consumption
end

-- 获取关联道具id
function Item:getAssociateId()
	return self.conf.associatedItemId
end

-- 是否是关联宝箱的道具
function Item:isAssociateBox()
	local id = self.tid
	local associateId = self:getAssociateId()
	if associateId then id = associateId end

	local count = #Enums.associatedItemIds
	for i = 1, count do
		if Enums.associatedItemIds[i] == tonumber(id) then
			return true 
		end
	end
end

function Item:getBindType()
	return self.bindType
end

function Item:getBindStr()
	local str = ""
	if self.bindType == 2 then
		str = L("lua_code_text_320")
	elseif self.bindType == 1 then
		str = L("lua_code_text_296")
	elseif self.bindType == 0 then
		str = L("tradable")
	end
	return str
end

-- 是否绑定
function Item:isBind()
	-- if self.bindType == 1 then
	-- 	return true
	-- elseif self.bindType == 2 then
	-- 	return self.bind and self.bind > 0
	-- end
	-- return false

	local isbind = false -- 默认没绑定
	if self.itemBagType == Enums.ItemBagType.equip then
		if UD:getItem( self.uid ) then -- 背包中？
			isbind = ( self.bind == 1 or self.bindType == 1 )
		elseif UD:getEquip( self.uid ) then -- 装备中？
			isbind = ( self.bindType == 2 or self.bindType == 1 )
		end
	elseif self.itemBagType == Enums.ItemBagType.item or
		self.itemBagType == Enums.ItemBagType.jewel then
			if UD:getItem( self.uid ) then -- 背包中？
				isbind = self.bindType == 1
			end
	end
	return isbind
end

-- 是否需要坚定
-- return able(是否可鉴定), cost(鉴定消耗)
function Item:getIdentify()
	-- 暂时没有坚定功能
	return false
	-- local costStr = self.conf.identifyCost
	-- local able = self.type == 6 and costStr ~= nil
	-- local cost = 0
	-- if able then
	-- 	local ary = string.split(costStr, "|")
	-- 	cost = tonumber(ary[3] or 0)
	-- end
	-- return able, cost
end

-- 是否可以使用 1.使用类型》0 2.等级达到 3.属于自己职业
function Item:isCanUse(lev)
	lev = lev or UD.player.level
	return self.useType > 0 and self.useLv <= lev and self:isClassEnable()
end

-- 是否可以快捷使用
function Item:isQuickUse()
	return self.conf.quickuse == "1"
end

-- 是否可以出售
function Item:isCanSell()
	-- TODO 出售逻辑混乱，暂时不出售，需要问一下策划的配置
	return false
	-- return self.conf.sellResource ~= nil
end
-- 是否可以自动出售
function Item:isCanAutoSell()
	return self:isCanSell() and self.quality == 1
end
-- 获得分解之后道具参数
function Item:getSellParams()
	if not self._sellType then
		local ary = string_split( self.conf.sellResource, "|" )
		self._sellType = tonumber( ary[1] ) -- 出售获得资源类型
		self._sellId = tonumber( ary[2] ) -- 出售获得道具Id
		self._sellNum = tonumber( ary[3] ) -- 出售获得道具数量
	end
	return self._sellType, self._sellId, self._sellNum
end
function Item:getSellPrice()
	if not self._sellNum then
		self:getSellParams()
	end
	return self._sellNum
end

-- 是否可以分解
function Item:isCanBreak()
	return self.conf.splitResource ~= nil
end
-- 是否可以自动分解
function Item:isCanAutoBreak()
	return self:isCanBreak() and self.quality <= 3
end
function Item:getBreakStr()
	return self.conf.splitResource
end
-- 获得分解之后道具参数
function Item:getBreakParams()
	if not self._breakType then
		local ary = string_split( self.conf.splitResource, "|" )
		self._breakType = tonumber( ary[1] ) -- 分解获得资源类型
		self._breakId = tonumber( ary[2] ) -- 分解获得道具Id
		self._breakNum = tonumber( ary[3] ) -- 分解获得道具数量
	end
	return self._breakType, self._breakId, self._breakNum
end

function Item:getBreakParamsByConf()
	if not self.conf.splitResource then return end		--Gm 装备没有配该字段
	return string_split(self.conf.splitResource, ";")
end

-- 是否可以追踪
function Item:isCanTrace()
	return self.trackNpcId > 0
end

function Item:setIsNewGet(isNew)
	self.isNew = isNew
end

function Item:toJson()
	return json.encode({uid=self.uid,tid=self.tid})
end

-- 拍卖行中出售商品界面背包分类
-- 是否是消耗品
function Item:isConsumables()
    local consumablesFlag = false
    if (self.subMenu >= AUCTIONSHOP_NORMAL_MINID and self.subMenu <= AUCTIONSHOP_NORMAL_MAXID) or
         (self.subMenu >= AUCTIONSHOP_BID_MINID and self.subMenu <= AUCTIONSHOP_BID_MAXID) then
        consumablesFlag = true
    end
    return consumablesFlag
end
------------------------------------------------------------------
-- 属性条卷轴（把道具包装成装备）
------------------------------------------------------------------
-- 构造一条额外属性的结构体
function Item:ctorExtraProp( extraProp )
	local temp = {}
	if extraProp then
		-- temp.index = tonumber( extraProp.index or -1 ) -- 属性诞生时候所处的槽位索引？
		temp.propID = tonumber( extraProp.propID or -1 )
		temp.quality = tonumber( extraProp.quality or -1 )
		temp.val = tonumber( extraProp.val or -1 )
		temp.posIdx = tonumber( extraProp.posIdx or -1 )
	end
	return temp
end

-- 属性条卷轴增加的属性(目前是一个卷轴只有一个数据)
function Item:getSpecialInfo()
	local info = self.conf.specialInfo
	if info then
		self.extraProps = {}
		local extraProp = {}
		local temp = string.splitTwice(info, {";", "|"}, true)
		for i, v in ipairs(temp) do
			extraProp.posIdx = v[3]
			extraProp.quality = v[4]
			extraProp.propID = v[5]
			extraProp.val = v[6]
			table.insert(self.extraProps, extraProp)
		end
	end
	--return self.extraProps
end

function Item:getPos()
	if self.conf.specialInfo then
		local temp = string_split(self.conf.specialInfo, "|")
		return temp[2] and tonumber(temp[2])
	end
end

-- 附加属性条目数
function Item:getExtraAttrNum()
	return self.extraProps and #self.extraProps or 1
end

-- 属性条卷轴，是否可以转移属性
function Item:canTransAttr()
	local flagTemp = false
	if self.conf.specialInfo and self:isClassEnable() then
		local euqipOnPlayer = UD:getEquipByPos( self:getPos() )
		if euqipOnPlayer and 0 < euqipOnPlayer:getExtraAttrNum() and 0 < self:getExtraAttrNum() then -- 人物身上存在同部位装备？
			local playerEquips = {}
			for _ ,v in pairs(euqipOnPlayer.extraProps or {}) do
				local propID = tonumber( v.propID or -1 ) or -1
				local val = tonumber( v.val or -1 ) or -1
				if propID ~= -1 and val ~= -1 then
					playerEquips[propID] = val
				end
			end

			local isFind = false
			for _, v in pairs(self.extraProps or {}) do
				local propID = tonumber( v.propID or -1 ) or -1
				local val = tonumber( v.val or -1 ) or -1
				if propID ~= -1 then
					local playerEquipVal = playerEquips[propID]
					if playerEquipVal then
						if val > playerEquipVal then
							isFind = true
							break
						end
					else
						isFind = true
						break
					end
				end
			end
			flagTemp = isFind
		end
	end
	return flagTemp
end

-- 万能属性条卷轴，是否可以转移属性
function Item:allAttrScrollCanTransAttr()
	local equips = UD:getCanTransAttrEquips()
	if #equips > 0 then
		return true
	end
	return false
end

-- 万能属性条卷轴，附加属性根据选中的装备的槽位而变化(目前是一个卷轴只有一个属性)
function Item:setExtraProps(id, index)
	if self.extraProps then
		self.extraProps[1].propID = id
		self.extraProps[1].posIdx = index
	end
end

return Item
